package infopanel;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.ParallelTransition;
import javafx.animation.ParallelTransitionBuilder;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.util.Duration;
import queues.QueuesClientWindowController;
import queues.UnknownSubjectException;
import server.QueueInfo;
import server.Subject;

/**
 *
 * @author Renato Rosa <2101076@my.ipleiria.pt>
 */
public class InfoPanelWindowController extends QueuesClientWindowController<InfoPanel> {

    @FXML
    private AnchorPane pane;
    private List<Label[]> labelRows;
    private Map<Integer, Label[]> rowIdx;
    private Paint originalPaint;

    public InfoPanelWindowController() {
        this.labelRows = new ArrayList<>();
        this.rowIdx = new HashMap<>();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        Set<Node> labels = pane.lookupAll("Label");
        // there are 3 labels in each row
        int rows = labels.size() / 3;

        for (int i = 0; i < rows; i++) {
            Label[] row = new Label[3];
            for (int j = 0; j < 3; j++) {
                String id = String.format("#%d%d", i, j);
                row[j] = (Label) pane.lookup(id);
            }
            labelRows.add(row);
        }
        originalPaint = labelRows.get(0)[0].getTextFill();
    }

    public void setQueueInfos(List<QueueInfo> queues) throws UnknownSubjectException {
        for (QueueInfo i : queues) {
            if (!i.getTicketText().isEmpty()) {
                updateQueue(i);
            }
        }
    }

    public void setSubjects(List<Subject> subjects) {
        for (int i = 0; i < subjects.size(); i++) {
            final Label l = labelRows.get(i)[0];
            final Subject a = subjects.get(i);
            rowIdx.put(a.getId(), labelRows.get(i));
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    l.setText(a.getName());
                }
            });
        }
    }

    public void updateQueue(final QueueInfo info) throws UnknownSubjectException {
        if (!rowIdx.containsKey(info.getSubjectId())) {
            throw new UnknownSubjectException();
        }

        List<Timeline> animations = new ArrayList<>(3);
        final Label[] row = rowIdx.get(info.getSubjectId());

        for (final Label l : row) {
            Timeline tm = new Timeline();
            KeyValue kv = new KeyValue(l.textFillProperty(), Color.WHITE, Interpolator.EASE_IN);
            KeyFrame kf = new KeyFrame(Duration.millis(400), kv);
            tm.setCycleCount(20);
            tm.setAutoReverse(true);
            tm.getKeyFrames().add(kf);
            tm.setOnFinished(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent t) {
                    l.setTextFill(originalPaint);
                }
            });
            animations.add(tm);
        }

        final ParallelTransition anim = ParallelTransitionBuilder.create().children(animations).build();
        
        final Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                row[1].setText(info.getWorkStationName());
                row[2].setText(info.getTicketText());
                anim.play();
                return null;
            }
        };
        
        task.setOnFailed(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent t) {
                System.err.println("Error updating screen: " + task.getException().getMessage());
            }
        });

        Platform.runLater(task);
    }
}
